Node.jsのORMライブラリのPrismaを使って、ECS(Fargate)からAuroraにクエリを実行してみた
こんにちは、ゲームソリューション部のsoraです。
今回は、Node.jsのORMライブラリのPrismaを使って、ECS(Fargate)からAuroraにクエリを実行してみたことについて書いていきます。
Auroraでのテーブル作成
APIサーバからAurora Serverlessにデータを挿入するためのテーブルを作成します。
今回はMySQLクライアントをインストールしたEC2から操作しました。
CREATE DATABASE mydatabase;
CREATE TABLE prefectures (
id INT AUTO_INCREMENT PRIMARY KEY,
prefecture VARCHAR(255),
prefectural_capital VARCHAR(255)
);
APIサーバの構築
ECS(Fargate)でAPIサーバを構築します。
以下ソースコードです。
説明はコメント内に記載しています。
今回はTypeScriptを使用しています。
ロガーとしてpino、フレームワークとしてExpressを使用しています。
import express from 'express';
import fs from 'fs';
import 'dotenv/config';
import { PrismaClient } from '@prisma/client';
// ログ出力ファイル指定
const logFileStream = fs.createWriteStream('/app/app.log', { flags: 'a' });
const logger = require('pino')(logFileStream);
const app = express();
// リクエストを受けるポート
const PORT = 3000;
// Feederテスト用
app.get('/feeder-test', async (req, res) => {
interface FeederTestQueryParams {
prefecture?: string;
prefectural_capital?: string;
}
const {prefecture, prefectural_capital} = req.query as FeederTestQueryParams;
const prisma = new PrismaClient();
try {
// 左側のprefectureとprefectural_capitalはDBのカラム名と一致させる
// createはデータのINSERT
await prisma.Prefectures.create({
data: {
prefecture: prefecture,
prefectural_capital: prefectural_capital,
},
});
logger.info({
msg: 'Insert OK',
prefecture: prefecture,
prefectural_capital: prefectural_capital
});
// findManyはSELECT
const select_result = await prisma.Prefectures.findMany();
logger.info({
msg: 'Select OK',
result: select_result
});
res.status(200).json({ message: 'OK'});
return;
} catch (error) {
const err = error as Error;
logger.error({
msg: 'Error executing query',
errMessage: err.message,
errStack: err.stack
});
res.status(500).json({ error: 'Database query failed' });
return;
} finally {
await prisma.$disconnect();
}
});
app.use((req, res) => {
logger.error('Not Found:', req.originalUrl);
res.status(404).json({ message: 'Not Found' });
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
package.json
{
"name": "ts",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "tsx index.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"typescript": "^5.6.2"
},
"dependencies": {
"@prisma/client": "^5.20.0",
"@types/express": "^5.0.0",
"@types/node": "^22.7.4",
"dotenv": "^16.4.5",
"express": "^4.21.0",
"fs": "^0.0.1-security",
"pino": "^9.4.0",
"prisma": "^5.20.0",
"tsx": "^4.19.1"
}
}
今回ORMライブラリとしてPrismaを使用します。
Prisma CLIとPrisma Clientをインストールして、Prismaの初期化をします。
npm install prisma
npm install @prisma/client
npx prisma init
初期化すると、prisma
ディレクトリが作成されて、その中のschema.prisma
ファイルにデータベースのスキーマを定義します。
schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model Prefectures {
id Int @id @default(autoincrement())
prefecture String
prefectural_capital String
@@map("prefectures")
}
schema.prisma
ファイルにて参照しているDATABASE_URL
を.env
に記載します。
.env
DATABASE_URL="mysql://[ユーザ名]:[パスワード]@[エンドポイント]:[ポート番号]/[データベース名]"
最後にECSで起動するため、Dockerfileを作成します。
Prismaを使用するため、Prisma Clientを生成しておきます。
FROM node:alpine
WORKDIR /app
RUN apk update
COPY /ts .
RUN npm install
# Prisma Clientの生成
RUN npx prisma generate
CMD ["npm", "run", "start"]
上記コードを使用してECRへイメージをpush、ECSでタスク定義、サービスとして起動します。
ちなみに、ログを確認するためにECS Execしようとしたところ、alpineイメージだとbashが入っていなかったため、shで接続しました。
$ aws ecs update-service --region [リージョン] --cluster [クラスタ名] --service [サービス名] --enable-execute-command
$ aws ecs describe-services --cluster [クラスタ名] --service [サービス名] | grep enableExecuteCommand
"enableExecuteCommand": true
# /bin/bashではなく/bin/sh
$ aws ecs execute-command \
--cluster [クラスタ名] \
--task [タスクARN] \
--container [コンテナ名] \
--command "/bin/sh" \
--interactive
実行
サービスが起動している状態で、必要なパラメータを含めてリクエストを実行します。
http://{タスクのパブリックIPアドレス}:3000/feeder-test?prefecture=Hyogo&prefectural_capital=Kobe
http://{タスクのパブリックIPアドレス}:3000/feeder-test?prefecture=Kanagawa&prefectural_capital=Yokohama
{ message: 'OK'}
が返ってきたため、テーブルを確認してみるとデータが登録されていました。
mysql> SELECT * from prefectures;
+----+------------+---------------------+
| id | prefecture | prefectural_capital |
+----+------------+---------------------+
| 1 | Hyogo | Kobe |
| 2 | Kanagawa | Yokohama |
+----+------------+---------------------+
2 rows in set (0.01 sec)
APIサーバにて出力したアプリログを確認してみると、データの登録、データの取得ができていることが確認できました。
{"level":30,"time":1728275785737,"pid":41,"hostname":"ip-10-0-11-67.ap-northeast-1.compute.internal","msg":"Insert OK","prefecture":"Hyogo","prefectural_capital":"Kobe"}
{"level":30,"time":1728275785739,"pid":41,"hostname":"ip-10-0-11-67.ap-northeast-1.compute.internal","msg":"Select OK","result":[{"id":1,"prefecture":"Hyogo","prefectural_capital":"Kobe"}]}
{"level":30,"time":1728275850314,"pid":41,"hostname":"ip-10-0-11-67.ap-northeast-1.compute.internal","msg":"Insert OK","prefecture":"Kanagawa","prefectural_capital":"Yokohama"}
{"level":30,"time":1728275850317,"pid":41,"hostname":"ip-10-0-11-67.ap-northeast-1.compute.internal","msg":"Select OK","result":[{"id":1,"prefecture":"Hyogo","prefectural_capital":"Kobe"},{"id":2,"prefecture":"Kanagawa","prefectural_capital":"Yokohama"}]}
最後に
今回は、Node.jsのORMライブラリのPrismaを使って、ECS(Fargate)からAuroraにクエリを実行してみたことを記事にしました。
どなたかの参考になると幸いです。